﻿//************************************************************************************************
// Copyright © 2014 Steven M. Cohn. All Rights Reserved.
// 
//************************************************************************************************

namespace River.Folderize
{
	using System;
	using System.Collections.Generic;
	using System.IO;
	using System.Windows.Media;
	using Microsoft.Win32;
	using River.WindowsAPICodePack.Shell;


	/// <summary>
	/// 
	/// </summary>

	internal class LibraryController
	{
		private const string FileType = ".library-ms";
		public const string EmptyIconRes = "imageres.dll,-1001";

		private string DefaultIconRes;
		private string libraryRootPath;
		private ImageSource emptyIcon;


		/// <summary>
		/// 
		/// </summary>

		public LibraryController ()
		{
			using (var root = ShellLibrary.LibrariesKnownFolder)
			{
				libraryRootPath = root.Path;
			}

			DefaultIconRes = null;
			using (var key = Registry.ClassesRoot.OpenSubKey(@"LibraryFolder\DefaultIcon"))
			{
				DefaultIconRes = (string)key.GetValue(null);
				if (!String.IsNullOrEmpty(DefaultIconRes))
				{
					DefaultIconRes = Environment.ExpandEnvironmentVariables(DefaultIconRes);
				}
			}

			if (DefaultIconRes == null)
			{
				DefaultIconRes = EmptyIconRes;
			}
		}


		/// <summary>
		/// 
		/// </summary>

		public ImageSource EmptyIcon
		{
			get
			{
				if (emptyIcon == null)
				{
					emptyIcon = ImageHelper.LoadIcon(EmptyIconRes, ImageHelper.ImageType.Library);
				}

				return emptyIcon;
			}
		}


		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>

		public List<LibraryFolder> GetLibraries ()
		{
			var libraries = new List<LibraryFolder>();

			using (var root = ShellLibrary.LibrariesKnownFolder)
			{
				var e = root.GetEnumerator();
				if (e != null)
				{
					while (e.MoveNext())
					{
						using (var lib = ShellLibrary.Load(e.Current.Name, root.Path, false))
						{
							var library = GetLibraryFolder(lib, root.Path);
							libraries.Add(library);
						}
					}
				}
			}

			libraries.Sort((LibraryFolder f1, LibraryFolder f2) =>
			{
				return String.Compare(f1.Name, f2.Name);
			});

			return libraries;
		}

		private LibraryFolder GetLibraryFolder (ShellLibrary library, string rootPath)
		{
			string guid = library.LibraryTypeId.ToString();
			var folder = new LibraryFolder(guid);
			folder.Name = library.Name;

			//folder.SetSystemFolder(shell.i

			folder.ImageRes = library.IconResourceId.ReferencePath;
			folder.Image = ImageHelper.LoadIcon(folder.ImageRes, ImageHelper.ImageType.Library);

			folder.Path = library.DefaultSaveFolder;
			folder.IsPinned = library.IsPinnedToNavigationPane;

			folder.DescriptionPath = Path.Combine(rootPath, library.Name + FileType);

			return folder;
		}


		#region LoadResourceString
		/*
		private string LoadResourceString (string descriptor)
		{
			var parts = descriptor.Split(',');
			string path = parts[0];
			int resID;
			if (!Int32.TryParse(parts[1], out resID))
			{
				return null;
			}

			if (handles == null)
			{
				// LoadLibraryEx handle cannot be closed; MSDN recommends caching these
				handles = new Dictionary<string, IntPtr>();
			}

			IntPtr handle = IntPtr.Zero;
			if (handles.ContainsKey(path))
			{
				handle = handles[path];
			}
			else
			{
				handle = Native.LoadLibraryEx(path, IntPtr.Zero, Native.LoadLibraryAsDatafile);
				if (handle != IntPtr.Zero)
				{
					handles.Add(path, handle);
				}
			}

			string value = null;

			if (handle != IntPtr.Zero)
			{
				var builder = new StringBuilder(40);
				int len = Native.LoadString(handle, resID > 0 ? resID : -resID, builder, 40);

				value = builder.ToString();
			}

			return value;
		}
		*/
		#endregion LoadResourceString


		/// <summary>
		/// 
		/// </summary>

		public void AddLibrary (LibraryFolder folder)
		{
			using (var lib = new ShellLibrary(folder.Name, libraryRootPath, true))
			{
				lib.LibraryType = LibraryFolderType.Generic;
				lib.IconResourceId = new IconReference(folder.ImageRes);

				var item = ShellFileSystemFolder.FromFolderPath(folder.Path);
				lib.Add(item);
			}

			folder.DescriptionPath = Path.Combine(libraryRootPath, folder.Name + FileType);
			folder.IsPinned = true;
		}


		/// <summary>
		/// 
		/// </summary>
		/// <param name="folder"></param>

		public void SaveProperties (LibraryFolder folder, LibraryFolder original)
		{
			string name = Path.GetFileNameWithoutExtension(original.DescriptionPath);
			string root = Path.GetDirectoryName(original.DescriptionPath);

			using (var lib = ShellLibrary.Load(original.Name, root, false))
			{
				if (!lib.Contains(folder.Path))
				{
					if (lib.Remove(lib.DefaultSaveFolder))
					{
						var item = ShellFileSystemFolder.FromFolderPath(folder.Path);
						lib.Add(item);
					}
				}

				lib.IconResourceId = new IconReference(folder.ImageRes);
			}

			if (!folder.Name.Equals(original.Name))
			{
				string newPath = Path.Combine(root, folder.Name + FileType);
				File.Move(original.DescriptionPath, newPath);
				folder.DescriptionPath = newPath;
			}
		}


		/// <summary>
		/// 
		/// </summary>
		/// <param name="path"></param>
		/// <returns></returns>

		public bool RemoveLibrary (string path)
		{
			if (File.Exists(path) && PathHelper.EnsureWritable(path))
			{
				try
				{
					File.Delete(path);
				}
				catch
				{
					return false;
				}
			}

			return true;
		}


		/// <summary>
		/// 
		/// </summary>
		/// <param name="path"></param>
		/// <param name="pinned"></param>

		public void SetPin (string path, bool pinned)
		{
			string name = Path.GetFileNameWithoutExtension(path);
			string root = Path.GetDirectoryName(path);

			using (var lib = ShellLibrary.Load(name, root, false))
			{
				lib.IsPinnedToNavigationPane = pinned;
			}
		}
	}
}
